Skip to content

[turbopack] update qfilter to 0.3.0-alpha#91467

Merged
lukesandberg merged 1 commit intocanaryfrom
update_qfilter
Mar 17, 2026
Merged

[turbopack] update qfilter to 0.3.0-alpha#91467
lukesandberg merged 1 commit intocanaryfrom
update_qfilter

Conversation

@lukesandberg
Copy link
Contributor

@lukesandberg lukesandberg commented Mar 16, 2026

What?

Update the qfilter crate to an alpha version.

Why?

Performance improvements in the quotient filter implementation used by turbo-persistence for SST file lookups.

Benchmark Results

Benchmarks run on Apple Silicon (M-series), comparing canary baseline vs this branch. Focused on qfilter-sensitive paths: the filter itself, SST lookups, uncompacted multi-commit DB reads, and writes.

qfilter microbenchmarks (direct filter operations)

Benchmark canary branch change
Lookup (hit)
1Ki entries 22.10 ns 14.63 ns -33.8%
10Ki entries 22.21 ns 15.41 ns -30.6%
100Ki entries 24.96 ns 17.47 ns -30.0%
1000Ki entries 25.05 ns 16.61 ns -33.7%
Lookup (miss)
1Ki entries 12.09 ns 9.19 ns -24.0%
10Ki entries 14.24 ns 11.07 ns -22.3%
100Ki entries 18.13 ns 13.72 ns -24.3%
1000Ki entries 13.36 ns 10.00 ns -25.2%
Insert (build filter)
1Ki entries 8.54 us 9.64 us +12.9%
10Ki entries 118.16 us 120.97 us +2.4%
100Ki entries 3.18 ms 2.57 ms -19.2%
1000Ki entries 20.88 ms 18.31 ms -12.3%

Summary: Lookups 22-34% faster across all sizes. Insert is slightly slower at small sizes but 12-19% faster at larger sizes where it matters most.

SST file lookup (filter + block read)

Benchmark canary branch change
Hit (uncached)
1Ki entries 2.52 us 2.52 us ~0%
10Ki entries 3.60 us 3.52 us -2.2%
100Ki entries 3.77 us 3.72 us -1.3%
1000Ki entries 6.65 us 6.55 us -1.5%
Miss (cached)
1Ki entries 124.50 ns 121.13 ns -2.7%
10Ki entries 168.18 ns 161.96 ns -3.7%
100Ki entries 195.97 ns 189.80 ns -3.1%
1000Ki entries 249.85 ns 235.68 ns -5.7%

Summary: Small but consistent improvements across SST lookups. Miss/cached shows the clearest gains (filter is the primary code path for rejecting misses).

DB-level reads (20 commits, uncompacted -- amplifies filter cost)

Benchmark canary branch change
10.67Mi entries
hit/uncached 3.49 us 3.13 us -10.3%
hit/cached 1.65 us 1.49 us -9.7%
miss/uncached 899.75 ns 746.28 ns -17.1%
miss/cached 793.51 ns 668.92 ns -15.7%
85.33Mi entries
hit/uncached 11.24 us 10.64 us ~0% (noisy)
hit/cached 4.53 us 4.10 us -9.5%
miss/uncached 5.01 us 4.36 us -13.0%
miss/cached 4.81 us 4.02 us -16.4%

Summary: 10-17% faster reads on uncompacted DBs with many SSTs. Miss paths benefit most since the filter rejects without I/O.

Write path (includes filter construction)

Benchmark canary branch change
85.33Ki entries 24.91 ms 23.42 ms -6.0%
853.33Ki entries 140.63 ms 131.84 ms -6.3%
8.33Mi entries 1.14 s 1.07 s -6.1%

Summary: ~6% faster writes across all sizes.

How?

Updated the qfilter dependency to a new alpha version with improved lookup and insert performance.

@nextjs-bot nextjs-bot added created-by: Turbopack team PRs by the Turbopack team. Turbopack Related to Turbopack with Next.js. labels Mar 16, 2026
Copy link
Contributor Author

lukesandberg commented Mar 16, 2026

@nextjs-bot
Copy link
Collaborator

nextjs-bot commented Mar 16, 2026

Failing test suites

Commit: c347912 | About building and testing Next.js

pnpm test-dev test/e2e/app-dir/app-basepath/index.test.ts (job)

  • app dir - basepath > should successfully hard navigate from pages -> app (DD)
Expand output

● app dir - basepath › should successfully hard navigate from pages -> app

page.waitForSelector: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('#page-2') to be visible

  545 |
  546 |     return this.startChain(async () => {
> 547 |       const el = await page.waitForSelector(selector, {
      |                             ^
  548 |         timeout,
  549 |         state,
  550 |       })

  at waitForSelector (lib/browsers/playwright.ts:547:29)
  at Playwright._chain (lib/browsers/playwright.ts:677:23)
  at Playwright._chain [as startChain] (lib/browsers/playwright.ts:658:17)
  at Playwright.startChain [as waitForElementByCss] (lib/browsers/playwright.ts:546:17)
  at Object.waitForElementByCss (e2e/app-dir/app-basepath/index.test.ts:16:19)

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 16, 2026

Merging this PR will not alter performance

✅ 17 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing update_qfilter (c347912) with canary (924d39d)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

## Benchmark: turbo-persistence — qfilter 0.3.0-alpha.2 vs 0.2.5

**Platform:** arm64 (Apple Silicon)

### Read (1 GiB compacted DB, 85.33Mi entries, 8-byte keys)

| Benchmark | 0.2.5 | 0.3.0-alpha.2 | Change | p-value |
|---|---|---|---|---|
| hit / uncached | 38.05 µs | 39.35 µs | +8.8% | 0.16 (noise) |
| hit / cached | 1.96 µs | 1.92 µs | **-2.3%** | 0.00 |
| miss / uncached | 213.0 ns | 208.4 ns | -1.5% | 0.00 |
| miss / cached | 178.5 ns | 188.0 ns | +3.6% | 0.00 |

### Write (8.33Mi entries)

| Benchmark | 0.2.5 | 0.3.0-alpha.2 | Change | p-value |
|---|---|---|---|---|
| write | 1.132 s | 1.109 s | **-2.0%** | 0.00 |

### Compaction (4Mi entries, 128 commits)

| Benchmark | 0.2.5 | 0.3.0-alpha.2 | Change | p-value |
|---|---|---|---|---|
| incremental | 17.41 ms | 17.94 ms | +3.0% | 0.30 (noise) |
| full | 546.9 ms | 553.9 ms | +1.3% | 0.11 (noise) |

### Summary

The upgrade from 0.2.5 to 0.3.0-alpha.2 is a **neutral-to-slight-improvement** in turbo-persistence benchmarks:
- **Write: -2.0%** — small but statistically significant improvement
- **Read hit/cached: -2.3%** — small improvement
- **Compaction:** no significant change
- No regressions outside noise
@nextjs-bot
Copy link
Collaborator

Stats from current PR

✅ No significant changes detected

📊 All Metrics
📖 Metrics Glossary

Dev Server Metrics:

  • Listen = TCP port starts accepting connections
  • First Request = HTTP server returns successful response
  • Cold = Fresh build (no cache)
  • Warm = With cached build artifacts

Build Metrics:

  • Fresh = Clean build (no .next directory)
  • Cached = With existing .next directory

Change Thresholds:

  • Time: Changes < 50ms AND < 10%, OR < 2% are insignificant
  • Size: Changes < 1KB AND < 1% are insignificant
  • All other changes are flagged to catch regressions

⚡ Dev Server

Metric Canary PR Change Trend
Cold (Listen) 456ms 456ms ▁▁▁▂▁
Cold (Ready in log) 440ms 440ms ▁▁▂▃▁
Cold (First Request) 827ms 819ms ▂▁▃▃▃
Warm (Listen) 456ms 456ms ▁▁▁▂▁
Warm (Ready in log) 439ms 440ms ▁▁▁▂▁
Warm (First Request) 336ms 336ms ▁▁▁▃▁
📦 Dev Server (Webpack) (Legacy)

📦 Dev Server (Webpack)

Metric Canary PR Change Trend
Cold (Listen) 557ms 558ms ▁▁▃▁▁
Cold (Ready in log) 526ms 523ms ▂▁▃▂▂
Cold (First Request) 2.362s 2.363s ▁▁▂▁▁
Warm (Listen) 559ms 558ms ▁▁▁▁▁
Warm (Ready in log) 521ms 517ms ▃▁▃▂▂
Warm (First Request) 2.355s 2.351s ▂▁▂▁▁

⚡ Production Builds

Metric Canary PR Change Trend
Fresh Build 3.887s 3.843s ▃▂▁▄▁
Cached Build 3.896s 3.881s ▂▂▁▄▁
📦 Production Builds (Webpack) (Legacy)

📦 Production Builds (Webpack)

Metric Canary PR Change Trend
Fresh Build 17.495s 17.635s ▁▁▁▁▁
Cached Build 17.612s 17.620s ▁▁▂▁▁
node_modules Size 483 MB 483 MB ▁▁▁▁█
📦 Bundle Sizes

Bundle Sizes

⚡ Turbopack

Client

Main Bundles
Canary PR Change
0~lwfcrlb4v_9.css gzip 115 B 115 B
00h0nz7r436~l.js gzip 13.3 kB N/A -
02ku7edzc_wf7.js gzip 450 B N/A -
03~yq9q893hmn.js gzip 39.4 kB 39.4 kB
04dv85sxifhcw.js gzip 156 B N/A -
057z-_itqqf-b.js gzip 48.5 kB N/A -
06da--2niyc4f.js gzip 160 B N/A -
08r5-6b-ppll5.js gzip 162 B N/A -
092lcb3fqrrf9.js gzip 8.52 kB N/A -
0aj~xs1l1g8tg.js gzip 8.53 kB N/A -
0c2g.labu7dli.js gzip 65.7 kB N/A -
0eg78sqvyqa0_.js gzip 13.7 kB N/A -
0gi3w58kp~oqc.js gzip 156 B N/A -
0h35gmp9u328z.js gzip 8.54 kB N/A -
0h6fkavebp.iz.js gzip 8.47 kB N/A -
0ino_yf1k3h6k.js gzip 10.4 kB N/A -
0kkm7tesfinr6.js gzip 12.9 kB N/A -
0lpm0ynr-5028.js gzip 7.61 kB N/A -
0lrrt986~5y12.js gzip 158 B N/A -
0m~2yy0-k0.0s.js gzip 169 B N/A -
0mhhjnycobiw0.js gzip 155 B N/A -
0moy~uao4dl.m.js gzip 9.19 kB N/A -
0ok23hm4ar8n~.js gzip 156 B N/A -
0q50rtpusjy90.js gzip 2.28 kB N/A -
0smgy2grrrlka.js gzip 8.58 kB N/A -
0t1dzhdfh0txh.js gzip 215 B 215 B
0vt7pofxnk8in.js gzip 10.1 kB N/A -
0waknu9.3t6oo.js gzip 155 B N/A -
0zid7o0-vupvp.js gzip 225 B N/A -
11yo3xfd6b147.js gzip 12.9 kB N/A -
12-b1bk6sxhe1.js gzip 153 B N/A -
12pz54pfp78.js gzip 70.8 kB N/A -
13.84hqxl_1p7.js gzip 9.76 kB N/A -
14dnd_9rpj0xq.js gzip 157 B N/A -
153924vhr4_fe.js gzip 158 B N/A -
1554wr-t7p6z-.js gzip 8.55 kB N/A -
15tjst79~qy3_.js gzip 1.46 kB N/A -
15z_v00ne4ud0.js gzip 8.47 kB N/A -
16-464sngeif-.js gzip 157 B N/A -
17d_m3p4j9w6r.js gzip 5.62 kB N/A -
17yu~3yiu7d2m.js gzip 8.52 kB N/A -
turbopack-0-..brh1.js gzip 4.17 kB N/A -
turbopack-0-..~z3i.js gzip 4.16 kB N/A -
turbopack-04..w73-.js gzip 4.16 kB N/A -
turbopack-09.._xb0.js gzip 4.16 kB N/A -
turbopack-0e..0770.js gzip 4.16 kB N/A -
turbopack-0h..kcas.js gzip 4.16 kB N/A -
turbopack-0t..wmn2.js gzip 4.16 kB N/A -
turbopack-0v..~ywt.js gzip 4.16 kB N/A -
turbopack-0v..wfoc.js gzip 4.16 kB N/A -
turbopack-12..54g7.js gzip 4.14 kB N/A -
turbopack-15..qxy..js gzip 4.16 kB N/A -
turbopack-15..~cak.js gzip 4.16 kB N/A -
turbopack-15..42.-.js gzip 4.16 kB N/A -
turbopack-16..mm6b.js gzip 4.16 kB N/A -
03t__~.5lvgeu.js gzip N/A 5.62 kB -
04d6ll75jqx3r.js gzip N/A 9.19 kB -
0583exyh-yhc7.js gzip N/A 9.76 kB -
072lv63r8dcz~.js gzip N/A 8.58 kB -
07ck-m4a5-5so.js gzip N/A 168 B -
07k6dcww5s4pu.js gzip N/A 13.7 kB -
0ar1~bwpezfgw.js gzip N/A 13.3 kB -
0c99mq1ez2bke.js gzip N/A 450 B -
0cbo6rhjf7w-6.js gzip N/A 156 B -
0cq-cmde_ws6u.js gzip N/A 8.47 kB -
0fwf102w10o9~.js gzip N/A 8.52 kB -
0gtmn.q_j1v5r.js gzip N/A 10.4 kB -
0h5~v-tahitcf.js gzip N/A 10.1 kB -
0j3.53ftqt4y3.js gzip N/A 155 B -
0ko7npzyoqvxn.js gzip N/A 156 B -
0l4d~z7ixj3wz.js gzip N/A 12.9 kB -
0le9gtymglk8m.js gzip N/A 65.7 kB -
0nclq9z6yzzm5.js gzip N/A 1.46 kB -
0nkn_f7bxhnni.js gzip N/A 153 B -
0nzumcogektg7.js gzip N/A 8.55 kB -
0s.c-cn5eebrx.js gzip N/A 8.47 kB -
0s6.ndj~wg5qp.js gzip N/A 70.8 kB -
0tj0jb~karm2q.js gzip N/A 157 B -
0tna7lg6q4zne.js gzip N/A 12.9 kB -
0vgt1zz9fdplj.js gzip N/A 160 B -
0votdfxr5fb5u.js gzip N/A 2.28 kB -
0wta5m-wk8slp.js gzip N/A 156 B -
0y6di8fz_8qyy.js gzip N/A 48.4 kB -
0y6r7p5ybjw0c.js gzip N/A 155 B -
0ykl9bs_qj.5..js gzip N/A 8.52 kB -
0zfen0tnxp4gh.js gzip N/A 8.55 kB -
10wkq1h9jzkg..js gzip N/A 225 B -
12u_his5dkcg..js gzip N/A 163 B -
13x7j-eiy1i9a.js gzip N/A 158 B -
149ndfh8zfcaz.js gzip N/A 8.53 kB -
168xlbkju2cj0.js gzip N/A 7.6 kB -
182e911.xpa71.js gzip N/A 156 B -
18c1kf~drwh4e.js gzip N/A 156 B -
turbopack-0....5ku.js gzip N/A 4.16 kB -
turbopack-04..oqi6.js gzip N/A 4.16 kB -
turbopack-05..6cp7.js gzip N/A 4.16 kB -
turbopack-09..mwo1.js gzip N/A 4.16 kB -
turbopack-0a..ba9o.js gzip N/A 4.16 kB -
turbopack-0c..0f0j.js gzip N/A 4.16 kB -
turbopack-0h..n9zu.js gzip N/A 4.16 kB -
turbopack-0p.._66z.js gzip N/A 4.16 kB -
turbopack-0q..rbnk.js gzip N/A 4.14 kB -
turbopack-0u..x~nx.js gzip N/A 4.16 kB -
turbopack-0v..hq2f.js gzip N/A 4.16 kB -
turbopack-0z..szyb.js gzip N/A 4.16 kB -
turbopack-10..qhh7.js gzip N/A 4.17 kB -
turbopack-13..lfek.js gzip N/A 4.16 kB -
Total 463 kB 463 kB ✅ -14 B

Server

Middleware
Canary PR Change
middleware-b..fest.js gzip 712 B 711 B
Total 712 B 711 B ✅ -1 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 426 B 429 B
Total 426 B 429 B ⚠️ +3 B

📦 Webpack

Client

Main Bundles
Canary PR Change
5528-HASH.js gzip 5.54 kB N/A -
6280-HASH.js gzip 60.3 kB N/A -
6335.HASH.js gzip 169 B N/A -
912-HASH.js gzip 4.59 kB N/A -
e8aec2e4-HASH.js gzip 62.7 kB N/A -
framework-HASH.js gzip 59.7 kB 59.7 kB
main-app-HASH.js gzip 255 B 252 B 🟢 3 B (-1%)
main-HASH.js gzip 39.2 kB 39.2 kB
webpack-HASH.js gzip 1.68 kB 1.68 kB
262-HASH.js gzip N/A 4.59 kB -
2889.HASH.js gzip N/A 169 B -
5602-HASH.js gzip N/A 5.55 kB -
6948ada0-HASH.js gzip N/A 62.7 kB -
9544-HASH.js gzip N/A 60.9 kB -
Total 234 kB 235 kB ⚠️ +653 B
Polyfills
Canary PR Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Total 39.4 kB 39.4 kB
Pages
Canary PR Change
_app-HASH.js gzip 194 B 194 B
_error-HASH.js gzip 183 B 180 B 🟢 3 B (-2%)
css-HASH.js gzip 331 B 330 B
dynamic-HASH.js gzip 1.81 kB 1.81 kB
edge-ssr-HASH.js gzip 256 B 256 B
head-HASH.js gzip 351 B 352 B
hooks-HASH.js gzip 384 B 383 B
image-HASH.js gzip 580 B 581 B
index-HASH.js gzip 260 B 260 B
link-HASH.js gzip 2.51 kB 2.51 kB
routerDirect..HASH.js gzip 320 B 319 B
script-HASH.js gzip 386 B 386 B
withRouter-HASH.js gzip 315 B 315 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Total 7.98 kB 7.98 kB ✅ -1 B

Server

Edge SSR
Canary PR Change
edge-ssr.js gzip 125 kB 125 kB
page.js gzip 269 kB 268 kB
Total 393 kB 393 kB ✅ -318 B
Middleware
Canary PR Change
middleware-b..fest.js gzip 618 B 614 B
middleware-r..fest.js gzip 156 B 155 B
middleware.js gzip 43.9 kB 43.7 kB
edge-runtime..pack.js gzip 842 B 842 B
Total 45.5 kB 45.3 kB ✅ -152 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 715 B 718 B
Total 715 B 718 B ⚠️ +3 B
Build Cache
Canary PR Change
0.pack gzip 4.27 MB 4.26 MB 🟢 7.21 kB (0%)
index.pack gzip 110 kB 111 kB
index.pack.old gzip 109 kB 109 kB
Total 4.49 MB 4.48 MB ✅ -6.96 kB

🔄 Shared (bundler-independent)

Runtimes
Canary PR Change
app-page-exp...dev.js gzip 333 kB 333 kB
app-page-exp..prod.js gzip 181 kB 181 kB
app-page-tur...dev.js gzip 332 kB 332 kB
app-page-tur..prod.js gzip 181 kB 181 kB
app-page-tur...dev.js gzip 329 kB 329 kB
app-page-tur..prod.js gzip 179 kB 179 kB
app-page.run...dev.js gzip 329 kB 329 kB
app-page.run..prod.js gzip 179 kB 179 kB
app-route-ex...dev.js gzip 76 kB 76 kB
app-route-ex..prod.js gzip 51.7 kB 51.7 kB
app-route-tu...dev.js gzip 76 kB 76 kB
app-route-tu..prod.js gzip 51.7 kB 51.7 kB
app-route-tu...dev.js gzip 75.6 kB 75.6 kB
app-route-tu..prod.js gzip 51.5 kB 51.5 kB
app-route.ru...dev.js gzip 75.6 kB 75.6 kB
app-route.ru..prod.js gzip 51.5 kB 51.5 kB
dist_client_...dev.js gzip 324 B 324 B
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 318 B 318 B
dist_client_...dev.js gzip 317 B 317 B
pages-api-tu...dev.js gzip 43.3 kB 43.3 kB
pages-api-tu..prod.js gzip 33 kB 33 kB
pages-api.ru...dev.js gzip 43.3 kB 43.3 kB
pages-api.ru..prod.js gzip 33 kB 33 kB
pages-turbo....dev.js gzip 52.7 kB 52.7 kB
pages-turbo...prod.js gzip 38.6 kB 38.6 kB
pages.runtim...dev.js gzip 52.7 kB 52.7 kB
pages.runtim..prod.js gzip 38.6 kB 38.6 kB
server.runti..prod.js gzip 62.4 kB 62.4 kB
Total 2.95 MB 2.95 MB ⚠️ +3 B
📎 Tarball URL
https://vercel-packages.vercel.app/next/commits/c3479127c0e3bdebc0dff2f64f0d97ae23981f18/next

@lukesandberg lukesandberg changed the title update qfilter [turbopack] update qfilter to 0.3.0-alpha Mar 17, 2026
@lukesandberg lukesandberg marked this pull request as ready for review March 17, 2026 17:44
@lukesandberg lukesandberg requested a review from a team March 17, 2026 17:45
@lukesandberg lukesandberg merged commit 4050a5b into canary Mar 17, 2026
289 of 292 checks passed
@lukesandberg lukesandberg deleted the update_qfilter branch March 17, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

created-by: Turbopack team PRs by the Turbopack team. Turbopack Related to Turbopack with Next.js.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants